#include "mockserverhandler.h"
#include <QTimer>

using namespace apollo;
using namespace apollo::core;
using namespace apollo::message::entity;

MockServerHandler::MockServerHandler(int socketDescriptor, QObject *parent) 
: QThread(parent), socketDescriptor(socketDescriptor)
{

}

MockServerHandler::~MockServerHandler()
{
	QLOG_INFO() <<  "Deleting MockServerHandler" ; 
	QLOG_INFO() << "Finished?" << this->isFinished();
	QLOG_INFO() << "IsRunning?" << this->isRunning();
	
	
}

void MockServerHandler::run()
{
	//moveToThread(this);
	socket = QSharedPointer<QTcpSocket>(new QTcpSocket);
	connect(socket.data(), SIGNAL(readyRead()), this, SLOT(read()));
	connect(socket.data(), SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error2(QAbstractSocket::SocketError)));
	if(socket->setSocketDescriptor(socketDescriptor) == false)
	{
		error2(socket->error());
		return;
	}
	QLOG_INFO() << " Created a connection with " << socket->peerAddress().toString() << ":" << socket->peerPort();
	stopped = false;

	//write("abc", 3);
	//WireFormat format;

	/*while(!stopped)
	{*/
	this->exec();
	//WireFormat::ReadState state = format.read(socket.dynamicCast<QAbstractSocket>(), payload);
	//}
	QLOG_INFO() << " stop event loop" ;
	if(socket.isNull() == false && socket->isOpen())
	{
		QLOG_INFO() << "Disconnecting from host";
		socket->disconnectFromHost();
	}

	emit finishedThread(this);
}

void MockServerHandler::read()
{
	QLOG_INFO()<< "Reading data: triggered by readyRead signal. ";
	while(socket->isValid() && socket->bytesAvailable() > 0)
	{
		PayloadPtr payload = format.unblockingRead(socket.dynamicCast<QAbstractSocket>(), ctx);
		if(ctx.state == WireFormat::Successful)
		{
			QLOG_INFO() << "Received a message. id = " << payload->getMessageId() << "type:" 
				<< payload->getMessageType() << "header:" << payload->getHeader() << "Body:"
				<< QTest::toHexRepresentation(payload->getBody(), payload->getBodySize());
			MessagePtr msg = payload->getMessage();
			std::string typeName = msg->GetTypeName();
			if(typeName == "apollo.message.entity.LoginRequest")
			{
				QSharedPointer<LoginRequest> loginReq = msg.dynamicCast<LoginRequest>();
				
				if(loginReq->loginid() == "ww")
				{
					ErrorMessage error;
					error.set_level(ErrorMessage_ErrorLevel_Error);
					error.set_messageid("APO_12_12");
					PayloadPtr payloadResp(new Payload);
					payloadResp->setBody(&error);
					payloadResp->setMessageId(Payload::MESSAGE_TYPE_APP);
					format.write(socket.dynamicCast<QAbstractSocket>(), payloadResp);
					socket->waitForBytesWritten(1000);
					QLOG_ERROR() << "Invalid User:" << loginReq->loginid();
					socket->abort();
					exit();
					break;
				}
				LoginResponse resp;
				resp.set_loginid("yy");
				resp.set_clientname("yi ying");
				PayloadPtr payloadResp(new Payload);
				payloadResp->setBody(&resp);
				payloadResp->setMessageId(Payload::MESSAGE_TYPE_APP);
				format.write(socket.dynamicCast<QAbstractSocket>(), payloadResp);
				//QThread::sleep(1);
				//format.write(socket.dynamicCast<QAbstractSocket>(), payloadResp);
				QTimer::singleShot(2000, this, SLOT(onSendMessage()));
				break;
			}
			format.write(socket.dynamicCast<QAbstractSocket>(), payload);
		}
		else if(ctx.state == WireFormat::NoAvailabeBytesError)
		{
			break;
		}
		else if(ctx.state == WireFormat::ChecksumError || ctx.state == WireFormat::MagicStringError
			|| ctx.state == WireFormat::MessageSizeError || ctx.state == WireFormat::TerminatorError)
		{
			QLOG_ERROR() << "Error, State:" << ctx.state;
			socket->abort();
			exit();
			break;
		}


	}
}

void MockServerHandler::write(char* data, int size)
{
	if(socket.isNull() == false)
	{
		if(socket->isOpen() == false)
		{
			socket->waitForConnected(10000);
		}
		if(socket->isOpen())
		{
			socket->write(data, size);
		}

	}
}
void MockServerHandler::onSendMessage()
{
	LoginResponse resp;
	resp.set_loginid("yy2");
	resp.set_clientname("yi ying2");

	PayloadPtr payloadResp(new Payload);
	payloadResp->setBody(&resp);
	payloadResp->setMessageId(Payload::MESSAGE_TYPE_APP);

	format.write(socket.dynamicCast<QAbstractSocket>(), payloadResp);

}
void MockServerHandler::error2(QAbstractSocket::SocketError socketError)
{
	QLOG_INFO()  << "MockServerHandler => error : " <<  socket ->errorString() << " in " << socket->peerAddress().toString();
	emit error(socket->peerAddress().toString(), socket->peerPort(),  socketError);
	QLOG_INFO()  << "stopping thread " ;
	stopped = true;
	this->quit();
}

void MockServerHandler::customEvent(QEvent *event)
{
	AnyEvent * anyEvent = dynamic_cast<AnyEvent *>(event);
	if(anyEvent != NULL)
	{

		QLOG_INFO()  << "current thread id in handler: " << QThread::currentThreadId() ;
		socket->write(anyEvent->getData(), anyEvent->getSize());
	}
	else 
	{
		QLOG_INFO() << "received event that is not AnyEvent";
	}


}
